package com.nowcoder.community.service;

import com.nowcoder.community.pojo.User;
import com.nowcoder.community.util.CommunityConstant;
import com.nowcoder.community.util.HostHolder;
import com.nowcoder.community.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

@Service("followService")
public class FollowService implements CommunityConstant {

    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplate;

    @Autowired
    @Qualifier("userService")
    private UserService userService;

    //关注
    public void follow(int userId, int entityType, int entityId){
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {

                String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);

                //开启redis事务
                operations.multi();

                operations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis());
                operations.opsForZSet().add(followerKey, userId, System.currentTimeMillis());

                //提交事务
                return operations.exec();
            }
        });
    }

    //取消关注
    public void unFollow(int userId, int entityType, int entityId){
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {

                String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);

                operations.multi();

                operations.opsForZSet().remove(followeeKey, entityId);
                operations.opsForZSet().remove(followerKey, userId);

                return operations.exec();
            }
        });
    }

    //查询关注的实体的数量
    public long findFolloweeCount(int userId, int entityType){

        String followeeKey = RedisKeyUtil.getFollowerKey(userId, entityType);

        return redisTemplate.opsForZSet().zCard(followeeKey);
        //redisTemplate.opsForZSet().zCard：查询zSet集合中key-value的数量
    }

    //查询实体粉丝的数量
    public long findFollowerCount(int entityType, int entityId){

        String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);

        return redisTemplate.opsForZSet().zCard(followerKey);
    }

    //查询当前用户是否已关注该实体
    public boolean hasFollowed(int userId, int entityType, int entityId){
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        return redisTemplate.opsForZSet().score(followeeKey, entityId) != null;
        //redisTemplate.opsForZSet().score：通过key和member获取排序的score
    }

    //查询某用户的关注的人
    public List<Map<String, Object>> findFollowees(int userId, int offset, int limit){
        //获取当前用户关注的人的key
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER);

        Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey,
                offset, offset + limit - 1);

        if (targetIds == null){
            return null;
        }

        List<Map<String, Object>> list = new ArrayList<>();

        for (Integer targetId : targetIds) {
            Map<String, Object> map = new HashMap<>();

            //查询当前用户关注的每个人
            User user = userService.findUserById(targetId);
            map.put("user", user);

            //查询当前用户关注的人的关注时间（zSet集合中的score）
            Double score = redisTemplate.opsForZSet().score(followeeKey, targetId);
            map.put("followeeTime", new Date(score.longValue()));

            list.add(map);
        }

        return list;
    }

    //查询某用户拥有的粉丝
    public List<Map<String, Object>> findFollowers(int userId, int offset, int limit){
        //获取用户粉丝的key
        String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId);

        Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followerKey,
                offset, offset + limit - 1);

        if (targetIds == null){
            return null;
        }

        List<Map<String, Object>> list = new ArrayList<>();

        for (Integer targetId : targetIds) {
            Map<String, Object> map = new HashMap<>();

            //查询关注当前用户的每个粉丝
            User user = userService.findUserById(targetId);
            map.put("user", user);

            //查询粉丝关注当前用户的时间（zSet集合中的score）
            Double score = redisTemplate.opsForZSet().score(followerKey, targetId);
            map.put("followerTime", new Date(score.longValue()));

            list.add(map);
        }

        return list;

    }

}
